home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 1 / QRZ Ham Radio Callsign Database - December 1993.iso / ucsd / packet / tcpip / sys5 / iscwmpst.z / iscwmpst / tcp / src / 8250.c next >
Encoding:
C/C++ Source or Header  |  1991-09-24  |  7.2 KB  |  383 lines

  1. /* @(#) $Header: 8250.c,v 1.10 91/09/24 05:52:17 deyke Exp $ */
  2.  
  3. #include <sys/types.h>
  4.  
  5. #include <fcntl.h>
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include <sys/socket.h>
  9. #include <termio.h>
  10. #include <unistd.h>
  11.  
  12. #if defined(ISC) || defined(SCO)
  13. #include <sys/tty.h>
  14. #include <sys/stream.h>
  15. #include <sys/ptem.h>
  16. #ifdef ISC
  17. #include <sys/pty.h>
  18. #endif
  19. #ifdef SCO
  20. #include <sys/vty.h>
  21. #endif
  22. #define FIOSNBIO        FIONBIO
  23. #endif
  24.  
  25. #include "global.h"
  26. #include "mbuf.h"
  27. #include "proc.h"
  28. #include "iface.h"
  29. #include "8250.h"
  30. #include "asy.h"
  31. #include "devparam.h"
  32. #include "buildsaddr.h"
  33. #include "hpux.h"
  34. #include "timer.h"
  35.  
  36. static int find_speed __ARGS((int speed));
  37. static int asy_open __ARGS((int dev));
  38. static void asy_tx __ARGS((struct asy *asyp));
  39.  
  40. struct asy Asy[ASY_MAX];
  41.  
  42. /*---------------------------------------------------------------------------*/
  43.  
  44. static struct {
  45.     int speed, flags;
  46. } speed_table[] = {
  47. #ifdef B50
  48.     50, B50,
  49. #endif
  50. #ifdef B75
  51.     75, B75,
  52. #endif
  53. #ifdef B110
  54.     110, B110,
  55. #endif
  56. #ifdef B134
  57.     134, B134,
  58. #endif
  59. #ifdef B150
  60.     150, B150,
  61. #endif
  62. #ifdef B200
  63.     200, B200,
  64. #endif
  65. #ifdef B300
  66.     300, B300,
  67. #endif
  68. #ifdef B600
  69.     600, B600,
  70. #endif
  71. #ifdef B900
  72.     900, B900,
  73. #endif
  74. #ifdef B1200
  75.     1200, B1200,
  76. #endif
  77. #ifdef B1800
  78.     1800, B1800,
  79. #endif
  80. #ifdef B2400
  81.     2400, B2400,
  82. #endif
  83. #ifdef B3600
  84.     3600, B3600,
  85. #endif
  86. #ifdef B4800
  87.     4800, B4800,
  88. #endif
  89. #ifdef B7200
  90.     7200, B7200,
  91. #endif
  92. #ifdef B9600
  93.     9600, B9600,
  94. #endif
  95. #ifdef B19200
  96.     19200, B19200,
  97. #endif
  98. #ifdef B38400
  99.     38400, B38400,
  100. #endif
  101.     -1, 0
  102. };
  103.  
  104. /*---------------------------------------------------------------------------*/
  105.  
  106. static int
  107. find_speed(speed)
  108. int speed;
  109. {
  110.     int i;
  111.  
  112.     i = 0;
  113.     while (speed_table[i].speed < speed && speed_table[i+1].speed > 0)
  114.         i++;
  115.     return i;
  116. }
  117.  
  118. /*---------------------------------------------------------------------------*/
  119.  
  120. static int
  121. asy_open(dev)
  122. int dev;
  123. {
  124.  
  125. #define MIN_WAIT (3*60)
  126. #define MAX_WAIT (3*60*60)
  127.  
  128.   static struct {
  129.     long  next;
  130.     long  wait;
  131.   } times[ASY_MAX];
  132.  
  133.   char  buf[80];
  134.   int  addrlen;
  135.   int  flags;
  136.   int  sp;
  137.   long  arg;
  138.   struct asy *ap;
  139.   struct iface *ifp;
  140.   struct sockaddr *addr;
  141.   struct termio termio;
  142.  
  143.   if (times[dev].next > secclock()) return (-1);
  144.   times[dev].wait *= 2;
  145.   if (times[dev].wait < MIN_WAIT) times[dev].wait = MIN_WAIT;
  146.   if (times[dev].wait > MAX_WAIT) times[dev].wait = MAX_WAIT;
  147.   times[dev].next = secclock() + times[dev].wait;
  148.   ap = Asy + dev;
  149.   ifp = ap->iface;
  150.   asy_stop(ifp);
  151.   if (!strncmp(ifp->name, "ipc", 3)) {
  152.     if (!(addr = build_sockaddr(ap->ipc_socket, &addrlen))) goto Fail;
  153.     if ((ap->fd = socket(addr->sa_family, SOCK_STREAM, 0)) < 0) goto Fail;
  154.     if (connect(ap->fd, addr, addrlen)) goto Fail;
  155.     if ((flags = fcntl(ap->fd, F_GETFL, 0)) == -1) goto Fail;
  156.     if (fcntl(ap->fd, F_SETFL, flags | O_NDELAY) == -1) goto Fail;
  157.     ap->speed = -1;
  158.   } else {
  159.     strcpy(buf, "/dev/");
  160.     strcat(buf, ifp->name);
  161.     if ((ap->fd = open(buf, O_RDWR, 0666)) < 0) goto Fail;
  162.     sp = find_speed(ap->speed);
  163.     ap->speed = speed_table[sp].speed;
  164.     termio.c_iflag = IGNBRK | IGNPAR;
  165.     termio.c_oflag = 0;
  166.     termio.c_cflag = speed_table[sp].flags | CS8 | CREAD | CLOCAL;
  167.     termio.c_lflag = 0;
  168.     termio.c_line = 0;
  169.     termio.c_cc[VMIN] = 0;
  170.     termio.c_cc[VTIME] = 0;
  171.     if (ioctl(ap->fd, TCSETA, &termio) == -1) goto Fail;
  172.     if (ioctl(ap->fd, TCFLSH, 2) == -1) goto Fail;
  173.     arg = 1;
  174.     ioctl(ap->fd, FIOSNBIO, &arg);      /*** will fail on pty master side ***/
  175.   }
  176.   times[dev].wait = 0;
  177.   on_read(ap->fd, (void (*)()) ifp->rxproc, ifp);
  178.   return 0;
  179.  
  180. Fail:
  181.   if (ap->fd > 0) close(ap->fd);
  182.   ap->fd = -1;
  183.   return (-1);
  184. }
  185.  
  186. /*---------------------------------------------------------------------------*/
  187.  
  188. /* Initialize asynch port "dev" */
  189. int
  190. asy_init(dev,iface,arg1,arg2,bufsize,trigchar,cts,rlsd,speed)
  191. int dev;
  192. struct iface *iface;
  193. char *arg1,*arg2;       /* Attach args for address and vector */
  194. int16 bufsize;
  195. int trigchar;
  196. char cts;
  197. char rlsd;
  198. int16 speed;
  199. {
  200.     register struct asy *ap;
  201.  
  202.     ap = &Asy[dev];
  203.     ap->iface = iface;
  204.     ap->ipc_socket = strdup(arg2);
  205.     ap->speed = speed;
  206.     asy_open(dev);
  207.     return 0;
  208. }
  209.  
  210. /*---------------------------------------------------------------------------*/
  211.  
  212. int
  213. asy_stop(iface)
  214. struct iface *iface;
  215. {
  216.     register struct asy *ap;
  217.  
  218.     ap = &Asy[iface->dev];
  219.  
  220.     if (ap->fd > 0) {
  221.         off_read(ap->fd);
  222.         off_write(ap->fd);
  223.         free_q(&ap->sndq);
  224.         close(ap->fd);
  225.         ap->fd = -1;
  226.     }
  227.     return 0;
  228. }
  229.  
  230. /*---------------------------------------------------------------------------*/
  231.  
  232. /* Set asynch line speed */
  233. int
  234. asy_speed(dev,bps)
  235. int dev;
  236. int16 bps;
  237. {
  238.  
  239.     struct asy *asyp;
  240.     int sp;
  241.     struct termio termio;
  242.  
  243.     if(bps == 0 || dev >= ASY_MAX)
  244.         return -1;
  245.     asyp = &Asy[dev];
  246.     if(asyp->iface == NULLIF)
  247.         return -1;
  248.  
  249.     if (asyp->fd <= 0 || !strncmp(asyp->iface->name, "ipc", 3))
  250.         return (-1);
  251.     sp = find_speed(bps);
  252.     if (ioctl(asyp->fd, TCGETA, &termio))
  253.         return (-1);
  254.     termio.c_cflag = (termio.c_cflag & ~CBAUD) | speed_table[sp].flags;
  255.     if (ioctl(asyp->fd, TCSETA, &termio))
  256.         return (-1);
  257.     asyp->speed = speed_table[sp].speed;
  258.     return 0;
  259. }
  260.  
  261. /*---------------------------------------------------------------------------*/
  262.  
  263. /* Asynchronous line I/O control */
  264. int32
  265. asy_ioctl(iface,cmd,set,val)
  266. struct iface *iface;
  267. int cmd;
  268. int set;
  269. int32 val;
  270. {
  271.     switch(cmd){
  272.     case PARAM_SPEED:
  273.         if(set)
  274.             asy_speed(iface->dev,(int16)val);
  275.         return Asy[iface->dev].speed;
  276.     };
  277.     return -1;
  278. }
  279.  
  280. /*---------------------------------------------------------------------------*/
  281.  
  282. int
  283. get_asy(dev, buf, cnt)
  284. int dev;
  285. char *buf;
  286. int cnt;
  287. {
  288.     struct asy *ap;
  289.  
  290.     ap = Asy + dev;
  291.     if (ap->fd <= 0 && asy_open(dev))
  292.         return 0;
  293.     cnt = read(ap->fd, buf, (unsigned) cnt);
  294.     ap->rxints++;
  295.     if (cnt <= 0) {
  296.         asy_stop(ap->iface);
  297.         return 0;
  298.     }
  299.     ap->rxchar += cnt;
  300.     if (ap->rxhiwat < cnt)
  301.         ap->rxhiwat = cnt;
  302.     return cnt;
  303. }
  304.  
  305. /*---------------------------------------------------------------------------*/
  306.  
  307. int
  308. doasystat(argc,argv,p)
  309. int argc;
  310. char *argv[];
  311. void *p;
  312. {
  313.     register struct asy *asyp;
  314.  
  315.     for(asyp = Asy;asyp < &Asy[ASY_MAX];asyp++){
  316.         if(asyp->iface == NULLIF)
  317.             continue;
  318.  
  319.         tprintf("%s:",asyp->iface->name);
  320.         tprintf(" %d bps\n",asyp->speed);
  321.  
  322.         tprintf(" RX: %lu int, %lu chr, %lu hw hi\n",
  323.             asyp->rxints,
  324.             asyp->rxchar,
  325.             asyp->rxhiwat);
  326.         asyp->rxhiwat = 0;
  327.  
  328.         if(tprintf(" TX: %lu int, %lu chr, %u q\n",
  329.             asyp->txints,
  330.             asyp->txchar,
  331.             len_p(asyp->sndq)) == EOF)
  332.             break;
  333.     }
  334.     return 0;
  335. }
  336.  
  337. /*---------------------------------------------------------------------------*/
  338.  
  339. /* Send a message on the specified serial line */
  340. int
  341. asy_send(dev,bp)
  342. int dev;
  343. struct mbuf *bp;
  344. {
  345.     struct asy *asyp;
  346.  
  347.     if(dev < 0 || dev >= ASY_MAX)
  348.         return -1;
  349.     asyp = &Asy[dev];
  350.     if (asyp->fd > 0 || !asy_open(dev)) {
  351.         append(&asyp->sndq, bp);
  352.         on_write(asyp->fd, (void (*)()) asy_tx, asyp);
  353.     } else
  354.         free_p(bp);
  355.     return 0;
  356. }
  357.  
  358. /*---------------------------------------------------------------------------*/
  359.  
  360. /* Serial transmit process, common to all protocols */
  361. static void
  362. asy_tx(asyp)
  363. struct asy *asyp;
  364. {
  365.     int  n;
  366.  
  367.     if (asyp->sndq != NULLBUF) {
  368.         n = write(asyp->fd, asyp->sndq->data, asyp->sndq->cnt);
  369.         if (n <= 0) {
  370.             asy_stop(asyp->iface);
  371.             return;
  372.         }
  373.         asyp->sndq->data += n;
  374.         asyp->sndq->cnt -= n;
  375.         asyp->txints++;
  376.         asyp->txchar += n;
  377.     }
  378.     while (asyp->sndq != NULLBUF && asyp->sndq->cnt == 0)
  379.         asyp->sndq = free_mbuf(asyp->sndq);
  380.     if (asyp->sndq == NULLBUF)
  381.         off_write(asyp->fd);
  382. }
  383.